/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package HashMatrix2;

import java.util.ArrayList;

/**
 *
 * @author mark_o
 */
public class LUFactorization implements ISolver{
    protected IMatrix L;
    protected IMatrix U;

    public LUFactorization(IMatrix matrix){
        int n = matrix.getN();
    	U = new  HashMatrix2(HashMatrix2.HASH_TYPE, n);
    	L = new  HashMatrix2(HashMatrix2.HASH_TYPE, n);
    		for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    U.setValue(0, i, matrix.getValue(0, i));
                    L.setValue(i, 0, matrix.getValue(i, 0)/U.getValue(0, 0));
                    double sum = 0;
                    
                        ArrayList<Integer> rowIndex = L.getJRowIndex(i);
                        int iterator = 0,k=0;
                        while((iterator<rowIndex.size())){
                            if((k=rowIndex.get(iterator))>=i){iterator++; continue;}
                            sum += L.getValue(i, k)* U.getValue(k, j);
                            iterator++;
                        }
                    U.setValue(i, j, matrix.getValue(i, j)-sum);
                    if (i <= j)
                    {
                        sum = 0;
                        rowIndex = L.getJRowIndex(j);
                        iterator = 0;
                        k=0;
                        while((iterator<rowIndex.size())){
                            if((k=rowIndex.get(iterator))>=i){iterator++; continue;}
                            sum += L.getValue(j, k)* U.getValue(k, i);
                            iterator++;
                        }
                        L.setValue(j, i, (matrix.getValue(j, i)-sum)/U.getValue(i, i));
                    }
                }
                //System.out.println(i);
            }
    }

    public double[] calculate(double[] b){
        /*System.out.print("\n===========UUUUUUUUU===============\n");
        for(int i=0;i<U.getN();i++){
        for(int j=0;j<U.getN();j++){
        System.out.print(U.getValue(i, j)+"\t");
        }
        System.out.print("\n");
        }


        System.out.print("\n===========LLLLLLLLLLLLL===============\n");
        for(int i=0;i<U.getN();i++){
        for(int j=0;j<U.getN();j++){
        System.out.print(L.getValue(i, j)+"\t");
        }
        System.out.print("\n");
        }*/

    	double[] y = new double[L.getN()];
        for(int i=0;i<L.getN();i++){

            double sum = 0;
            ArrayList<Integer> rowIndex = L.getJRowIndex(i);
            int iterator = 0;
            int k=0;
            while((iterator<rowIndex.size())){
                if((k=rowIndex.get(iterator))>=i){iterator++; continue;}
                sum += L.getValue(i, k)* y[k];
                iterator++;
            }
			y[i] = (b[i]-sum);
		}

		double[] x = new double[L.getN()];




        for (int row = (U.getN()-1); row>=0; row--){
            double sum = 0;
            ArrayList<Integer> rowIndex = U.getJRowIndex(row);
            int iterator = 0;
            int k=0;
            while((iterator<rowIndex.size())){
                if((k=rowIndex.get(iterator))<=row){iterator++; continue;}
                sum += U.getValue(row, k)* x[k];
                iterator++;
            }
               x[row] = (y[row]-sum)/U.getValue(row,row);
            }

    	return x;
    }
}
